package com.example.demo.auth.service.impl;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.jdbc.core.BeanPropertyRowMapper;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.core.RowMapper;
import org.springframework.stereotype.Service;

import com.example.demo.auth.constant.HnybConstants;
import com.example.demo.auth.dto.UserExtDTO;
import com.example.demo.domain.vo.AreaInfo;
import com.example.demo.domain.vo.LoginInfo;
import com.example.demo.domain.vo.LogonUser;
import com.example.demo.domain.vo.MenuResource;
import com.example.demo.domain.vo.SecurityUserService;
import com.example.demo.domain.vo.UserInfoHN;
import com.example.demo.domain.vo.UserRole;
import com.utils.StringUtils;
import com.utils.db.SqlArgument;
import com.utils.db.SqlUtils;



/**
 * 河南医保用户权限服务
 * @author: fred
 * @version: 1.0
 * @date: 2018/4/12
 */
@Service("securityUserService")
public class HnybSecurityUserServiceImpl implements SecurityUserService {
	@Autowired
    private JdbcTemplate jdbcTemplate;
	private final static String MARK = "?";
    private final static String SEP = ",";

    @Override
    public LogonUser login(LoginInfo loginInfo) {
    	//domainid 设置成默认100
        String sql="select nid as userId,account as loginname,name as username from v_idm_user where account=? and account_enable='T'";
        RowMapper<LogonUser> rm = new  BeanPropertyRowMapper(LogonUser.class);
        Object[] params = {loginInfo.getLoginName()};
        LogonUser logonUser =  jdbcquery(sql,params,rm).get(0);
        //LogonUser logonUser =  jdbcTemplate.queryForList(sql,rm,loginInfo.getLoginName()).get(0);

        if(logonUser==null)
            return null;
        
        logonUser.setDomainId(HnybConstants.DEFAULT_DOMAINID);
       
        

        //系统扩展的用户信息

        //String userExtSql="select b.user_id as portalUserId,a.id as portalUnitId,a.nid as organId, a.name as organName,c.aab301 as areaCode,c.aab302 as areaName from v_idm_unit a, v_idm_unit_user b ,v_org_unit_ext c where a.nid = b.nunitid and a.nid=c.nid  and b.nuserid = ?";
        String userExtSql="select b.user_id as portalUserId,a.id as portalUnitId,a.nid as organId,a.code, a.name as organName,c.aab301 as areaCode,c.aab302 as areaName,c.aaa027 from v_idm_unit a, v_idm_unit_user b ,v_org_unit_ext c where a.nid = b.nunitid and a.nid=c.nid  and b.nuserid = ?";
        RowMapper<UserExtDTO> rm1 = new  BeanPropertyRowMapper(UserExtDTO.class);
        Object[] params1 = {logonUser.getUserId()};
        //UserExtDTO userExtDto =jdbcTemplate.queryForList(userExtSql,UserExtDTO.class,logonUser.getUserId()).get(0);
        UserExtDTO userExtDto = jdbcquery(userExtSql,params1,rm1).get(0);
        logonUser.setOrganId(userExtDto.getOrganId());
        logonUser.setOrganName(userExtDto.getOrganName()); 
        
        UserInfoHN userinfo = new UserInfoHN();
        BeanUtils.copyProperties(userExtDto, userinfo);
        logonUser.setExtInfo(userinfo);
        //行政区划
        AreaInfo areaInfo = new AreaInfo();
        areaInfo.setAreaCode(userExtDto.getAreaCode());
        areaInfo.setAreaName(userExtDto.getAreaName());
        logonUser.setAreaInfo(areaInfo);
        //角色信息 如果角色ID重复把角色类型加进ID的hash规则里
        StringBuilder rolesb = new StringBuilder("select nroleid as roleId from v_idm_admin_role_user a join v_idm_admin_role b on a.nroleid=b.nid  where  a.nuserid = ?")
        		.append(" union ") 
        		.append("select nroleid as roleId from v_idm_busi_role_user a join v_idm_busi_role b on a.nroleid=b.nid where  a.nuserid = ?") ;
        //List<UserRole> roles = jdbcTemplate.queryForList(rolesb.toString(), UserRole.class,logonUser.getUserId(),logonUser.getUserId() );
        RowMapper<UserRole> rm2 = new  BeanPropertyRowMapper(UserRole.class);
        Object[] params2 = {logonUser.getUserId(),logonUser.getUserId()};
        List<UserRole> roles = jdbcquery(rolesb.toString(),params2,rm2);
        logonUser.setRoles(roles);
        //加载资源信息
        if(roles!=null && roles.size()>0){
        	
	        Set<String> roleIdSet = new HashSet();
	        for(UserRole urole : roles){
	        	roleIdSet.add(urole.getRoleId());
	        }
	        userinfo.setRoleIdSet(roleIdSet);
	        List<MenuResource> menuResources = getRoleResources(roleIdSet);
	        if(menuResources!=null){
	        	Set<String> urls = new HashSet<String>();
	        	for(MenuResource mr :menuResources){
	        		urls.add(mr.getUrl());
	        	}
	        	userinfo.setUrlSet(urls);
	        }
	        
	        
        }
        
        //统筹区
        return logonUser;
    }

    @Override
    public void logout(LogonUser logonUser) {


    }

    @Override
    public List<MenuResource> getRoleResources(Set<String> set) {
        List<MenuResource> menuResources = new ArrayList<MenuResource>();

        
        StringBuilder ressb = new StringBuilder("select a.nid as id,a.name,a.npid as parentId,a.url,'1' as type from v_idm_module a ,v_idm_resource_authority b where a.nid=b.nresourceid and (1=2 ");
        
        if(set==null || set.size()==0){
        	return menuResources;
        }
        for(String roleid:set){
        	ressb.append(" or b.nroleid= ?");
        }
        ressb.append(")");
        RowMapper<MenuResource> rm2 = new  BeanPropertyRowMapper(MenuResource.class);
        //List<UserRole> roles = jdbcquery(rolesb.toString(),params2,rm2);
        //menuResources = jdbcTemplate.queryForList(ressb.toString(), MenuResource.class,set.toArray(new String[0]) );
        menuResources = jdbcquery(ressb.toString(),set.toArray(new String[0]),rm2);
        return menuResources;
    }
    
    /**
     * jdbc查询
     *
     * @param sql
     * @param params
     * @param rowMapper
     * @return
     */
    private <R> List<R> jdbcquery(String sql, Object[] params, RowMapper<R> rowMapper) {
        SqlArgument trueArgument = SqlUtils.getSqlArgument(sql,params);
        List<R> list;
        list = jdbcTemplate.query(trueArgument.getText(), trueArgument.getArgs(), rowMapper);
        return list;
    }
    @SuppressWarnings("unchecked")
    public static SqlArgument getSqlArgument(String sql, Object[] params) {
        SqlArgument sqlArgument = new SqlArgument();
        if(params.length==1 && params[0] instanceof Map){
            sqlArgument.setText(sql);
            sqlArgument.setNamedQuery(true);
            sqlArgument.setParamMap((Map<String, Object>)params[0]);
            return sqlArgument;
        }
        //检查下是否有Collection参数，将其展开
        boolean hasMultiValue = false;
        for (Object param : params) {
            if (param == null) {
                continue;
            }
            if (param instanceof Collection) {
                hasMultiValue = true;
                break;
            } else if (param.getClass().isArray()) {
                hasMultiValue = true;
                break;
            }
        }

        if (hasMultiValue) {
            String[] sqlSections = StringUtils.splitPreserveAllTokens(sql, MARK);
            StringBuilder sb = new StringBuilder(sql.length());
            List<Object> args = new ArrayList<Object>();
            sb.append(sqlSections[0]);
            for (int i = 0; i < params.length; i++) {
                Object param = params[i];
                String seq = MARK;
                if (param != null) {
                    if (param instanceof Collection) {
                        Collection collection = (Collection) param;
                        args.addAll(collection);
                        seq = org.apache.commons.lang3.StringUtils.repeat(MARK, SEP, collection.size());
                    } else if (param.getClass().isArray()) {
                        Object[] arr = (Object[]) param;
                        args.addAll(Arrays.asList(arr));
                        seq = StringUtils.repeat(MARK, SEP, args.size());
                    } else {
                        args.add(param);
                    }
                } else {
                    args.add(null);
                }
                sb.append(seq).append(sqlSections[i + 1]);
            }
            sqlArgument.setText(sb.toString());
            sqlArgument.setArgs(args.toArray());
        } else {
            if (sql.indexOf(MARK) == sql.lastIndexOf(MARK) && params.length > 1) {
                //视作唯一的数组参数
                sqlArgument.setText(StringUtils.replace(sql, MARK, StringUtils.repeat(MARK, SEP, params.length)));
                sqlArgument.setArgs(params);
            } else {
                sqlArgument.setText(sql);
                sqlArgument.setArgs(params);
            }
        }
        return sqlArgument;
    }
}
